case class Sphere(center: Vec3, radius: Double, material: Material) extends Hittable:
  override def hit(r: Ray, t_min: Double, t_max: Double) =
    val oc = r.origin - center
    val a = dot(r.direction, r.direction)
    val half_b = dot(oc, r.direction)
    val c = oc.length_squared - radius * radius
    val discriminant = half_b * half_b - a * c
    if discriminant < 0 then
      None
    else
      val sqrtd = math.sqrt(discriminant)
      var root = (-half_b - sqrtd) / a
      if root < t_min || t_max < root then
        root = (-half_b + sqrtd) / a
        if root < t_min || t_max < root then
          return None
      

      val t = root
      val p = r.at(t)
      val outward_normal = (p - center) / radius
      val record = HitRecord(
        t=t,
        p=p,
        normal=(p - center) / radius,
        front_face=false,
        material=material
      )
      record.set_face_normal(r, outward_normal)
      Some(record)